home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / tcpin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-03  |  23.9 KB  |  875 lines

  1. /* Process incoming TCP segments. Page number references are to ARPA RFC-793,
  2.  * the TCP specification.
  3.  * 941003  added TCP access control dc0hk
  4.  */
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "icmp.h"
  12. #include "iface.h"
  13. #include "ip.h"
  14. #include "config.h"
  15.  
  16. static void near update __ARGS((struct tcb *tcb,struct tcp *seg,int16 length));
  17. static void near proc_syn __ARGS((struct tcb *tcb,char tos,struct tcp *seg));
  18. static void near add_reseq __ARGS((struct tcb *tcb,char tos,struct tcp *seg,
  19.     struct mbuf *bp,int16 length));
  20. static void near get_reseq __ARGS((struct tcb *tcb,char *tos,struct tcp *seq,
  21.     struct mbuf **bp,int16 *length));
  22. static int near trim __ARGS((struct tcb *tcb,struct tcp *seg,struct mbuf **bpp,
  23.     int16 *length));
  24. static int near in_window __ARGS((struct tcb *tcb,int32 seq));
  25.  
  26. /* This function is called from IP with the IP header in machine byte order,
  27.  * along with a mbuf chain pointing to the TCP header.
  28.  */
  29. void
  30. tcp_input(iface,ip,bp,rxbroadcast)
  31. struct iface *iface;    /* Incoming interface (ignored) */
  32. struct ip *ip;            /* IP header */
  33. struct mbuf *bp;        /* Data field, if any */
  34. int rxbroadcast;        /* Incoming broadcast - discard if true */
  35. {
  36.     struct tcb *ntcb, *tcb;        /* TCP Protocol control block */
  37.     struct tcp seg;                /* Local copy of segment header */
  38.     struct connection conn;        /* Local copy of addresses */
  39.     struct pseudo_header ph;    /* Pseudo-header for checksumming */
  40.     int hdrlen;                    /* Length of TCP header */
  41.     int16 length;
  42.  
  43.     if(bp == NULLBUF)
  44.         return;
  45.  
  46.     tcpInSegs++;
  47.     if(rxbroadcast)
  48.         /* Any TCP packet arriving as a broadcast is
  49.          * to be completely IGNORED!! */
  50.         goto discard;
  51.  
  52.     length = ip->length - IPLEN - ip->optlen;
  53.     ph.source = ip->source;
  54.     ph.dest = ip->dest;
  55.     ph.protocol = ip->protocol;
  56.     ph.length = length;
  57.     if(cksum(&ph,bp,length) != 0) {
  58.         /* Checksum failed, ignore segment completely */
  59.         tcpInErrs++;
  60.         goto discard;
  61.     }
  62.     /* Form local copy of TCP header in host byte order */
  63.     if((hdrlen = ntohtcp(&seg,&bp)) < 0)
  64.         /* TCP header is too small */
  65.         goto discard;
  66.  
  67.     length -= hdrlen;
  68.  
  69.     /* Fill in connection structure and find TCB */
  70.     conn.local.address = ip->dest;
  71.     conn.local.port = seg.dest;
  72.     conn.remote.address = ip->source;
  73.     conn.remote.port = seg.source;
  74.  
  75.     if((tcb = lookup_tcb(&conn)) == NULLTCB){
  76.         /* If this segment doesn't carry a SYN, reject it */
  77.         if(!seg.flags.syn)
  78.             goto discard2;
  79.  
  80. #ifdef  TCPACCESS
  81.     if(tcp_check(TCPaccess,ip->source,seg.dest) != 0 ) {
  82.         free_p(bp);
  83.         reset(ip,&seg);
  84.         goto discard;
  85.             }
  86. #endif
  87.                                                     
  88.  
  89.         /* See if there's a TCP_LISTEN on this socket with
  90.          * unspecified remote address and port
  91.          */
  92.         conn.remote.address = 0;
  93.         conn.remote.port = 0;
  94.         if((tcb = lookup_tcb(&conn)) == NULLTCB) {
  95.             /* Nope, try unspecified local address too */
  96.             conn.local.address = 0;
  97.             if((tcb = lookup_tcb(&conn)) == NULLTCB)
  98.                 /* No LISTENs, so reject */
  99.                 goto discard2;
  100.         }
  101.         /* We've found an server listen socket, so clone the TCB */
  102.         if(tcb->flags.clone) {
  103.             ntcb = (struct tcb *)mxallocw(sizeof (struct tcb));
  104.             ASSIGN(*ntcb,*tcb);
  105.             tcb = ntcb;
  106.             tcb->timer.arg = tcb;
  107.             tcb->next = Tcbs;
  108.             Tcbs = tcb;
  109.         }
  110.  
  111.         /* Put all the socket info into the TCB */
  112.         tcb->conn.local.address = ip->dest;
  113.         tcb->conn.remote.address = ip->source;
  114.         tcb->conn.remote.port = seg.source;
  115.     }
  116.     tcb->flags.congest = ip->flags.congest;
  117.     /* Do unsynchronized-state processing (p. 65-68) */
  118.     switch(tcb->state){
  119.     case TCP_CLOSED:
  120.         goto discard2;
  121.     case TCP_LISTEN:
  122.         if(seg.flags.rst)
  123.             goto discard;
  124.  
  125.         if(seg.flags.ack)
  126.             goto discard2;
  127.  
  128.         if(seg.flags.syn){
  129.             /* (Security check is bypassed) */
  130.             /* page 66 */
  131.             proc_syn(tcb,ip->tos,&seg);
  132.             send_syn(tcb);
  133.             setstate(tcb,TCP_SYN_RECEIVED);
  134.             if(length != 0 || seg.flags.fin) {
  135.                 /* Continue processing if there's more */
  136.                 break;
  137.             }
  138.             tcp_output(tcb);
  139.         }
  140.         /* Unlikely to get here directly */
  141.         goto discard;
  142.     case TCP_SYN_SENT:
  143.         if(seg.flags.ack){
  144.             if(!seq_within(seg.ack,tcb->iss+1,tcb->snd.nxt))
  145.                 goto discard2;
  146.         }
  147.         if(seg.flags.rst){    /* p 67 */
  148.             if(seg.flags.ack){
  149.                 /* The ack must be acceptable since we just checked it.
  150.                  * This is how the remote side refuses connect requests.
  151.                  */
  152.                 close_self(tcb,RESET);
  153.             }
  154.             goto discard;
  155.         }
  156.         /* (Security check skipped here) */
  157.         /* Check incoming precedence; it must match if there's an ACK */
  158.         if(seg.flags.ack && PREC(ip->tos) != PREC(tcb->tos))
  159.             goto discard2;
  160.  
  161.         if(seg.flags.syn){
  162.             proc_syn(tcb,ip->tos,&seg);
  163.             if(seg.flags.ack){
  164.                 /* Our SYN has been acked, otherwise the ACK
  165.                  * wouldn't have been valid.
  166.                  */
  167.                 update(tcb,&seg,length);
  168.                 setstate(tcb,TCP_ESTABLISHED);
  169.             } else {
  170.                 setstate(tcb,TCP_SYN_RECEIVED);
  171.             }
  172.             if(length != 0 || seg.flags.fin) {
  173.                 break;        /* Continue processing if there's more */
  174.             }
  175.             tcp_output(tcb);
  176.         } else {
  177.             free_p(bp);    /* Ignore if neither SYN or RST is set */
  178.         }
  179.         return;
  180.     }
  181.     /* We reach this point directly in any synchronized state. Note that
  182.      * if we fell through from LISTEN or SYN_SENT processing because of a
  183.      * data-bearing SYN, window trimming and sequence testing "cannot fail".
  184.      */
  185.  
  186.     /* Trim segment to fit receive window. */
  187.     if(trim(tcb,&seg,&bp,&length) == -1){
  188.         /* Segment is unacceptable */
  189.         if(!seg.flags.rst){    /* NEVER answer RSTs */
  190.             /* In SYN_RECEIVED state, answer a retransmitted SYN
  191.              * with a retransmitted SYN/ACK.
  192.              */
  193.             if(tcb->state == TCP_SYN_RECEIVED)
  194.                 tcb->snd.ptr = tcb->snd.una;
  195.             tcb->flags.force = 1;
  196.             tcp_output(tcb);
  197.         }
  198.         return;
  199.     }
  200.     /* If segment isn't the next one expected, and there's data
  201.      * or flags associated with it, put it on the resequencing
  202.      * queue, ACK it and return.
  203.      *
  204.      * Processing the ACK in an out-of-sequence segment without
  205.      * flags or data should be safe, however.
  206.      */
  207.     if(seg.seq != tcb->rcv.nxt
  208.      && (length != 0 || seg.flags.syn || seg.flags.fin)){
  209.         add_reseq(tcb,ip->tos,&seg,bp,length);
  210.         tcb->flags.force = 1;
  211.         tcp_output(tcb);
  212.         return;
  213.     }
  214.     /* This loop first processes the current segment, and then
  215.      * repeats if it can process the resequencing queue.
  216.      */
  217.     for(;;){
  218.         /* We reach this point with an acceptable segment; all data and flags
  219.          * are in the window, and the starting sequence number equals rcv.nxt
  220.          * (p. 70)
  221.          */
  222.         if(seg.flags.rst){
  223.             if(tcb->state == TCP_SYN_RECEIVED
  224.              && !tcb->flags.clone && !tcb->flags.active){
  225.                 /* Go back to listen state only if this was
  226.                  * not a cloned or active server TCB
  227.                  */
  228.                 setstate(tcb,TCP_LISTEN);
  229.             } else {
  230.                 close_self(tcb,RESET);
  231.             }
  232.             goto discard;
  233.         }
  234.         /* (Security check skipped here) p. 71 */
  235.         /* Check for precedence mismatch or erroneous extra SYN */
  236.         if(PREC(ip->tos) != PREC(tcb->tos) || seg.flags.syn)
  237.             goto discard2;
  238.  
  239.         /* Check ack field p. 72 */
  240.         if(!seg.flags.ack)
  241.             goto discard;    /* All segments after synchronization must have ACK */
  242.  
  243.         /* Process ACK */
  244.         switch(tcb->state){
  245.         case TCP_SYN_RECEIVED:
  246.             if(seq_within(seg.ack,tcb->snd.una+1,tcb->snd.nxt)){
  247.                 update(tcb,&seg,length);
  248.                 setstate(tcb,TCP_ESTABLISHED);
  249.             } else {
  250.                 goto discard2;
  251.             }
  252.             break;
  253.         case TCP_ESTABLISHED:
  254.         case TCP_CLOSE_WAIT:
  255.             update(tcb,&seg,length);
  256.             break;
  257.         case TCP_FINWAIT1:    /* p. 73 */
  258.             update(tcb,&seg,length);
  259.             if(tcb->sndcnt == 0){
  260.                 /* Our FIN is acknowledged */
  261.                 setstate(tcb,TCP_FINWAIT2);
  262.             }
  263.             break;
  264.         case TCP_FINWAIT2:
  265.             update(tcb,&seg,length);
  266.             break;
  267.         case TCP_CLOSING:
  268.             update(tcb,&seg,length);
  269.             if(tcb->sndcnt == 0){
  270.                 /* Our FIN is acknowledged */
  271.                 setstate(tcb,TCP_TIME_WAIT);
  272.                 set_timer(&tcb->timer,MSL2 * 1000L);
  273.                 start_timer(&tcb->timer);
  274.             }
  275.             break;
  276.         case TCP_LAST_ACK:
  277.             update(tcb,&seg,length);
  278.             if(tcb->sndcnt == 0){
  279.                 /* Our FIN is acknowledged, close connection */
  280.                 close_self(tcb,NORMAL);
  281.                 return;
  282.             }
  283.             break;
  284.         case TCP_TIME_WAIT:
  285.             start_timer(&tcb->timer);
  286.             break;
  287.         }
  288.  
  289.         /* (URGent bit processing skipped here) */
  290.  
  291.         /* Process the segment text, if any, beginning at rcv.nxt (p. 74) */
  292.         if(length != 0){
  293.             switch(tcb->state){
  294.             case TCP_SYN_RECEIVED:
  295.             case TCP_ESTABLISHED:
  296.             case TCP_FINWAIT1:
  297.             case TCP_FINWAIT2:
  298.                 /* Place on receive queue */
  299.                 append(&tcb->rcvq,bp);
  300.                 tcb->rcvcnt += length;
  301.                 tcb->rcv.nxt += length;
  302.                 tcb->rcv.wnd -= length;
  303.                 tcb->flags.force = 1;
  304.                 /* Notify user */
  305.                 if(tcb->r_upcall)
  306.                     (*tcb->r_upcall)(tcb,tcb->rcvcnt);
  307.                 break;
  308.             default:
  309.                 /* Ignore segment text */
  310.                 goto discard;
  311.             }
  312.         }
  313.         /* process FIN bit (p 75) */
  314.         if(seg.flags.fin){
  315.             tcb->flags.force = 1;    /* Always respond with an ACK */
  316.  
  317.             switch(tcb->state){
  318.             case TCP_SYN_RECEIVED:
  319.             case TCP_ESTABLISHED:
  320.                 tcb->rcv.nxt++;
  321.                 setstate(tcb,TCP_CLOSE_WAIT);
  322.                 break;
  323.             case TCP_FINWAIT1:
  324.                 tcb->rcv.nxt++;
  325.                 if(tcb->sndcnt == 0){
  326.                     /* Our FIN has been acked; bypass TCP_CLOSING state */
  327.                     setstate(tcb,TCP_TIME_WAIT);
  328.                     set_timer(&tcb->timer,MSL2 * 1000L);
  329.                     start_timer(&tcb->timer);
  330.                 } else {
  331.                     setstate(tcb,TCP_CLOSING);
  332.                 }
  333.                 break;
  334.             case TCP_FINWAIT2:
  335.                 tcb->rcv.nxt++;
  336.                 setstate(tcb,TCP_TIME_WAIT);
  337.                 set_timer(&tcb->timer,MSL2 * 1000L);
  338.                 start_timer(&tcb->timer);
  339.                 break;
  340.             case TCP_CLOSE_WAIT:
  341.             case TCP_CLOSING:
  342.             case TCP_LAST_ACK:
  343.                 break;        /* Ignore */
  344.             case TCP_TIME_WAIT:    /* p 76 */
  345.                 start_timer(&tcb->timer);
  346.                 break;
  347.             }
  348.             /* Call the client again so he can see EOF */
  349.             if(tcb->r_upcall)
  350.                 (*tcb->r_upcall)(tcb,tcb->rcvcnt);
  351.         }
  352.         /* Scan the resequencing queue, looking for a segment we can handle,
  353.          * and freeing all those that are now obsolete.
  354.          */
  355.         while(tcb->reseq != NULLRESEQ && seq_ge(tcb->rcv.nxt,tcb->reseq->seg.seq)){
  356.             get_reseq(tcb,&ip->tos,&seg,&bp,&length);
  357.             if(trim(tcb,&seg,&bp,&length) == 0)
  358.                 goto gotone;
  359.             /* Segment is an old one; trim has freed it */
  360.         }
  361.         break;
  362. gotone:    ;
  363.     }
  364.     tcp_output(tcb);    /* Send any necessary ack */
  365.     return;
  366. discard:
  367.     free_p(bp);
  368.     return;
  369. discard2:
  370.     free_p(bp);
  371.     reset(ip,&seg);
  372.     return;
  373. }
  374.  
  375. /* Process an incoming ICMP response */
  376. void
  377. tcp_icmp(icsource,source,dest,type,code,bpp)
  378. int32 icsource;            /* Sender of ICMP message (not used) */
  379. int32 source;            /* Original IP datagram source (i.e. us) */
  380. int32 dest;                /* Original IP datagram dest (i.e., them) */
  381. char type,code;            /* ICMP error codes */
  382. struct mbuf **bpp;        /* First 8 bytes of TCP header */
  383. {
  384.     struct tcp seg;
  385.     struct connection conn;
  386.     struct tcb *tcb;
  387.  
  388.     /* Extract the socket info from the returned TCP header fragment
  389.      * Note that since this is a datagram we sent, the source fields
  390.      * refer to the local side.
  391.      */
  392.     ntohtcp(&seg,bpp);
  393.     conn.local.port = seg.source;
  394.     conn.remote.port = seg.dest;
  395.     conn.local.address = source;
  396.     conn.remote.address = dest;
  397.     if((tcb = lookup_tcb(&conn)) == NULLTCB)
  398.         return;    /* Unknown connection, ignore */
  399.  
  400.     /* Verify that the sequence number in the returned segment corresponds
  401.      * to something currently unacknowledged. If not, it can safely
  402.      * be ignored.
  403.      */
  404.     if(!seq_within(seg.seq,tcb->snd.una,tcb->snd.nxt))
  405.         return;
  406.  
  407.     /* Destination Unreachable and Time Exceeded messages never kill a
  408.      * connection; the info is merely saved for future reference.
  409.      */
  410.     switch(uchar(type)){
  411.     case ICMP_DEST_UNREACH:
  412.     case ICMP_TIME_EXCEED:
  413.         tcb->type = type;
  414.         tcb->code = code;
  415.         break;
  416.     case ICMP_QUENCH:
  417.         /* Source quench; cut the congestion window in half,
  418.          * but don't let it go below one packet
  419.          */
  420.         tcb->cwind /= 2;
  421.         tcb->cwind = max(tcb->mss,tcb->cwind);
  422.         break;
  423.     }
  424. }
  425.  
  426. /* Send an acceptable reset (RST) response for this segment
  427.  * The RST reply is composed in place on the input segment
  428.  */
  429. void
  430. reset(ip,seg)
  431. struct ip *ip;            /* Offending IP header */
  432. struct tcp *seg;        /* Offending TCP header */
  433. {
  434.     struct mbuf *hbp;
  435.     struct pseudo_header ph;
  436.     int16 tmp;
  437.  
  438.     if(seg->flags.rst)
  439.         return;    /* Never send an RST in response to an RST */
  440.  
  441.     /* Compose the RST IP pseudo-header, swapping addresses */
  442.     ph.source = ip->dest;
  443.     ph.dest = ip->source;
  444.     ph.protocol = TCP_PTCL;
  445.     ph.length = TCPLEN;
  446.  
  447.     /* Swap port numbers */
  448.     tmp = seg->source;
  449.     seg->source = seg->dest;
  450.     seg->dest = tmp;
  451.  
  452.     if(seg->flags.ack){
  453.         /* This reset is being sent to clear a half-open connection.
  454.          * Set the sequence number of the RST to the incoming ACK
  455.          * so it will be acceptable.
  456.          */
  457.         seg->flags.ack = 0;
  458.         seg->seq = seg->ack;
  459.         seg->ack = 0;
  460.     } else {
  461.         /* We're rejecting a connect request (SYN) from TCP_LISTEN state
  462.          * so we have to "acknowledge" their SYN.
  463.          */
  464.         seg->flags.ack = 1;
  465.         seg->ack = seg->seq;
  466.         seg->seq = 0;
  467.         if(seg->flags.syn)
  468.             seg->ack++;
  469.     }
  470.     /* Set remaining parts of packet */
  471.     seg->flags.urg = 0;
  472.     seg->flags.psh = 0;
  473.     seg->flags.rst = 1;
  474.     seg->flags.syn = 0;
  475.     seg->flags.fin = 0;
  476.     seg->wnd = 0;
  477.     seg->up = 0;
  478.     seg->mss = 0;
  479.     seg->optlen = 0;
  480.     if((hbp = htontcp(seg,NULLBUF,&ph)) == NULLBUF)
  481.         return;
  482.     /* Ship it out (note swap of addresses) */
  483.     ip_send(ip->dest,ip->source,TCP_PTCL,ip->tos,0,hbp,ph.length,0,0);
  484.     tcpOutRsts++;
  485. }
  486.  
  487. /* Process an incoming acknowledgement and window indication.
  488.  * From page 72.
  489.  */
  490. static void near
  491. update(tcb,seg,length)
  492. struct tcb *tcb;
  493. struct tcp *seg;
  494. int16 length;
  495. {
  496.     int16 acked = 0, expand;
  497.  
  498.     if(seq_gt(seg->ack,tcb->snd.nxt)){
  499.         tcb->flags.force = 1;    /* Acks something not yet sent */
  500.         return;
  501.     }
  502.     /* Decide if we need to do a window update.
  503.      * This is always checked whenever a legal ACK is received,
  504.      * even if it doesn't actually acknowledge anything,
  505.      * because it might be a spontaneous window reopening.
  506.      */
  507.     if(seq_gt(seg->seq,tcb->snd.wl1) || ((seg->seq == tcb->snd.wl1)
  508.      && seq_ge(seg->ack,tcb->snd.wl2))){
  509.         /* If the window had been closed, crank back the
  510.          * send pointer so we'll immediately resume transmission.
  511.          * Otherwise we'd have to wait until the next probe.
  512.          */
  513.         if(tcb->snd.wnd == 0 && seg->wnd != 0)
  514.             tcb->snd.ptr = tcb->snd.una;
  515.         tcb->snd.wnd = seg->wnd;
  516.         tcb->snd.wl1 = seg->seq;
  517.         tcb->snd.wl2 = seg->ack;
  518.     }
  519.     /* See if anything new is being acknowledged */
  520.     if(!seq_gt(seg->ack,tcb->snd.una)){
  521.         if(seg->ack != tcb->snd.una)
  522.             return;    /* Old ack, ignore */
  523.  
  524.         if(length != 0 || seg->flags.syn || seg->flags.fin)
  525.             return;    /* Nothing acked, but there is data */
  526.  
  527.         /* Van Jacobson "fast recovery" code */
  528.         if(++tcb->dupacks == TCPDUPACKS){
  529.             /* We've had a burst of do-nothing acks, so
  530.              * we almost certainly lost a packet.
  531.              * Resend it now to avoid a timeout. (This is
  532.              * Van Jacobson's 'quick recovery' algorithm.)
  533.              */
  534.             int32 ptrsave;
  535.  
  536.             /* Knock the threshold down just as though
  537.              * this were a timeout, since we've had
  538.              * network congestion.
  539.              */
  540.             tcb->ssthresh = tcb->cwind/2;
  541.             tcb->ssthresh = max(tcb->ssthresh,tcb->mss);
  542.  
  543.             /* Manipulate the machinery in tcp_output() to
  544.              * retransmit just the missing packet
  545.              */
  546.             ptrsave = tcb->snd.ptr;
  547.             tcb->snd.ptr = tcb->snd.una;
  548.             tcb->cwind = tcb->mss;
  549.             tcp_output(tcb);
  550.             tcb->snd.ptr = ptrsave;
  551.  
  552.             /* "Inflate" the congestion window, pretending as
  553.              * though the duplicate acks were normally acking
  554.              * the packets beyond the one that was lost.
  555.              */
  556.             tcb->cwind = tcb->ssthresh + TCPDUPACKS*tcb->mss;
  557.         } else if(tcb->dupacks > TCPDUPACKS){
  558.             /* Continue to inflate the congestion window
  559.              * until the acks finally get "unstuck".
  560.              */
  561.             tcb->cwind += tcb->mss;
  562.         }
  563.         return;
  564.     }
  565.     if(tcb->dupacks >= TCPDUPACKS && tcb->cwind > tcb->ssthresh){
  566.         /* The acks have finally gotten "unstuck". So now we
  567.          * can "deflate" the congestion window, i.e. take it
  568.          * back down to where it would be after slow start
  569.          * finishes.
  570.          */
  571.         tcb->cwind = tcb->ssthresh;
  572.     }
  573.     tcb->dupacks = 0;
  574.  
  575.     /* We're here, so the ACK must have actually acked something */
  576.     acked = seg->ack - tcb->snd.una;
  577.  
  578.     /* Expand congestion window if not already at limit and if
  579.      * this packet wasn't retransmitted
  580.      */
  581.     if(tcb->cwind < tcb->snd.wnd && !tcb->flags.retran){
  582.         if(tcb->cwind < tcb->ssthresh){
  583.             /* Still doing slow start/CUTE, expand by amount acked */
  584.             expand = min(acked,tcb->mss);
  585.         } else {
  586.             /* Steady-state test of extra path capacity */
  587.             expand = ((long)tcb->mss * tcb->mss) / tcb->cwind;
  588.         }
  589.         /* Guard against arithmetic overflow */
  590.         if(tcb->cwind + expand < tcb->cwind)
  591.             expand = MAXINT16 - tcb->cwind;
  592.  
  593.         /* Don't expand beyond the offered window */
  594.         if(tcb->cwind + expand > tcb->snd.wnd)
  595.             expand = tcb->snd.wnd - tcb->cwind;
  596.  
  597.         if(expand != 0){
  598. #ifdef    XXX
  599.             /* Kick up the mean deviation estimate to prevent
  600.              * unnecessary retransmission should we already be
  601.              * bandwidth limited
  602.              */
  603.             tcb->mdev += ((long)tcb->srtt * expand) / tcb->cwind;
  604. #endif
  605.             tcb->cwind += expand;
  606.         }
  607.     }
  608.     /* Round trip time estimation */
  609.     if(tcb->flags.rtt_run && seq_ge(seg->ack,tcb->rttseq)){
  610.         /* A timed sequence number has been acked */
  611.         tcb->flags.rtt_run = 0;
  612.         if(!(tcb->flags.retran)){
  613.             int32 rtt;    /* measured round trip time */
  614.             int32 abserr;    /* abs(rtt - srtt) */
  615.  
  616.             /* This packet was sent only once and now
  617.              * it's been acked, so process the round trip time
  618.              */
  619.             rtt = msclock() - tcb->rtt_time;
  620.  
  621.             abserr = (rtt > tcb->srtt) ? rtt - tcb->srtt : tcb->srtt - rtt;
  622.             /* Run SRTT and MDEV integrators, with rounding */
  623.             tcb->srtt = ((AGAIN-1)*tcb->srtt + rtt + (AGAIN/2)) >> LAGAIN;
  624.             tcb->mdev = ((DGAIN-1)*tcb->mdev + abserr + (DGAIN/2)) >> LDGAIN;
  625.  
  626.             rtt_add(tcb->conn.remote.address,rtt);
  627.             /* Reset the backoff level */
  628.             tcb->backoff = 0;
  629.         }
  630.     }
  631.     tcb->sndcnt -= acked;    /* Update virtual byte count on snd queue */
  632.     tcb->snd.una = seg->ack;
  633.  
  634.     /* If we're waiting for an ack of our SYN, note it and adjust count */
  635.     if(!(tcb->flags.synack)){
  636.         tcb->flags.synack = 1;
  637.         acked--;    /* One less byte to pull from real snd queue */
  638.     }
  639.     /* Remove acknowledged bytes from the send queue and update the
  640.      * unacknowledged pointer. If a FIN is being acked,
  641.      * pullup won't be able to remove it from the queue, but that
  642.      * causes no harm.
  643.      */
  644.     pullup(&tcb->sndq,NULLCHAR,acked);
  645.  
  646.     /* Stop retransmission timer, but restart it if there is still
  647.      * unacknowledged data. If there is no more unacked data,
  648.      * the transmitter has gone at least momentarily idle, so
  649.      * record the time for the VJ restart-slowstart rule.
  650.      */
  651.     stop_timer(&tcb->timer);
  652.     if(tcb->snd.una != tcb->snd.nxt)
  653.         start_timer(&tcb->timer);
  654.     else
  655.         tcb->lastactive = msclock();
  656.  
  657.     /* If retransmissions have been occurring, make sure the
  658.      * send pointer doesn't repeat ancient history
  659.      */
  660.     if(seq_lt(tcb->snd.ptr,tcb->snd.una))
  661.         tcb->snd.ptr = tcb->snd.una;
  662.  
  663.     /* Clear the retransmission flag since the oldest
  664.      * unacknowledged segment (the only one that is ever retransmitted)
  665.      * has now been acked.
  666.      */
  667.     tcb->flags.retran = 0;
  668.  
  669.     /* If outgoing data was acked, notify the user so he can send more
  670.      * unless we've already sent a FIN.
  671.      */
  672.     if(acked != 0 && tcb->t_upcall
  673.      && (tcb->state == TCP_ESTABLISHED || tcb->state == TCP_CLOSE_WAIT)){
  674.         (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  675.     }
  676. }
  677.  
  678. /* Determine if the given sequence number is in our receiver window.
  679.  * NB: must not be used when window is closed!
  680.  */
  681. static int near
  682. in_window(tcb,seq)
  683. struct tcb *tcb;
  684. int32 seq;
  685. {
  686.     return seq_within(seq,tcb->rcv.nxt,(int32)(tcb->rcv.nxt+tcb->rcv.wnd-1));
  687. }
  688.  
  689. /* Process an incoming SYN */
  690. static void near
  691. proc_syn(tcb,tos,seg)
  692. struct tcb *tcb;
  693. char tos;
  694. struct tcp *seg;
  695. {
  696.     int16 mtu;
  697.     struct tcp_rtt *tp;
  698.  
  699.     tcb->flags.force = 1;    /* Always send a response */
  700.  
  701.     /* Note: It's not specified in RFC 793, but SND.WL1 and
  702.      * SND.WND are initialized here since it's possible for the
  703.      * window update routine in update() to fail depending on the
  704.      * IRS if they are left unitialized.
  705.      */
  706.     /* Check incoming precedence and increase if higher */
  707.     if(PREC(tos) > PREC(tcb->tos))
  708.         tcb->tos = tos;
  709.     tcb->rcv.nxt = seg->seq + 1;    /* p 68 */
  710.     tcb->snd.wl1 = tcb->irs = seg->seq;
  711.     tcb->snd.wnd = seg->wnd;
  712.     if(seg->mss != 0)
  713.         tcb->mss = seg->mss;
  714.     /* Check the MTU of the interface we'll use to reach this guy
  715.      * and lower the MSS so that unnecessary fragmentation won't occur
  716.      */
  717.     if((mtu = ip_mtu(tcb->conn.remote.address)) != 0){
  718.         /* Allow space for the TCP and IP headers */
  719.         mtu -= TCPLEN + IPLEN;
  720.         tcb->cwind = tcb->mss = (int16)min(mtu,tcb->mss);
  721.     }
  722.     /* See if there's round-trip time experience */
  723.     if((tp = rtt_get(tcb->conn.remote.address)) != NULLRTT){
  724.         tcb->srtt = tp->srtt;
  725.         tcb->mdev = tp->mdev;
  726.     }
  727. }
  728.  
  729. /* Generate an initial sequence number and put a SYN on the send queue */
  730. void
  731. send_syn(tcb)
  732. struct tcb *tcb;
  733. {
  734.     tcb->iss = geniss();
  735.     tcb->rttseq = tcb->snd.wl2 = tcb->snd.una = tcb->iss;
  736.     tcb->snd.ptr = tcb->snd.nxt = tcb->rttseq;
  737.     tcb->sndcnt++;
  738.     tcb->flags.force = 1;
  739. }
  740.  
  741. /* Add an entry to the resequencing queue in the proper place */
  742. static void near
  743. add_reseq(tcb,tos,seg,bp,length)
  744. struct tcb *tcb;
  745. char tos;
  746. struct tcp *seg;
  747. struct mbuf *bp;
  748. int16 length;
  749. {
  750.     struct reseq *rp, *rp1;
  751.  
  752.     /* Allocate reassembly descriptor */
  753.     if((rp = (struct reseq *)mxallocw(sizeof (struct reseq))) == NULLRESEQ){
  754.         /* No space, toss on floor */
  755.         free_p(bp);
  756.         return;
  757.     }
  758.     ASSIGN(rp->seg,*seg);
  759.     rp->tos = tos;
  760.     rp->bp = bp;
  761.     rp->length = length;
  762.  
  763.     /* Place on reassembly list sorting by starting seq number */
  764.     rp1 = tcb->reseq;
  765.     if(rp1 == NULLRESEQ || seq_lt(seg->seq,rp1->seg.seq)){
  766.         /* Either the list is empty, or we're less than all other
  767.          * entries; insert at beginning.
  768.          */
  769.         rp->next = rp1;
  770.         tcb->reseq = rp;
  771.     } else {
  772.         /* Find the last entry less than us */
  773.         for(;;){
  774.             if(rp1->next == NULLRESEQ || seq_lt(seg->seq,rp1->next->seg.seq)){
  775.                 /* We belong just after this one */
  776.                 rp->next = rp1->next;
  777.                 rp1->next = rp;
  778.                 break;
  779.             }
  780.             rp1 = rp1->next;
  781.         }
  782.     }
  783. }
  784.  
  785. /* Fetch the first entry off the resequencing queue */
  786. static void near
  787. get_reseq(tcb,tos,seg,bp,length)
  788. struct tcb *tcb;
  789. char *tos;
  790. struct tcp *seg;
  791. struct mbuf **bp;
  792. int16 *length;
  793. {
  794.     struct reseq *rp;
  795.  
  796.     if((rp = tcb->reseq) == NULLRESEQ)
  797.         return;
  798.  
  799.     tcb->reseq = rp->next;
  800.  
  801.     *tos = rp->tos;
  802.     ASSIGN(*seg,rp->seg);
  803.     *bp = rp->bp;
  804.     *length = rp->length;
  805.     xfree((char *)rp);
  806. }
  807.  
  808. /* Trim segment to fit window. Return 0 if OK, -1 if segment is
  809.  * unacceptable.
  810.  */
  811. static int near
  812. trim(tcb,seg,bpp,length)
  813. struct tcb *tcb;
  814. struct tcp *seg;
  815. struct mbuf **bpp;
  816. int16 *length;
  817. {
  818.     long dupcnt, excess;
  819.     int16 len = *length;        /* Segment length including flags */
  820.     char accept = 0;
  821.  
  822.     if(seg->flags.syn)
  823.         len++;
  824.     if(seg->flags.fin)
  825.         len++;
  826.  
  827.     /* Acceptability tests */
  828.     if(tcb->rcv.wnd == 0){
  829.         /* Only in-order, zero-length segments are acceptable when
  830.          * our window is closed.
  831.          */
  832.         if(seg->seq == tcb->rcv.nxt && len == 0){
  833.             return 0;    /* Acceptable, no trimming needed */
  834.         }
  835.     } else {
  836.         /* Some part of the segment must be in the window */
  837.         if(in_window(tcb,seg->seq)){
  838.             accept++;    /* Beginning is */
  839.         } else if(len != 0){
  840.             if(in_window(tcb,(int32)(seg->seq+len-1)) || /* End is */
  841.              seq_within(tcb->rcv.nxt,seg->seq,(int32)(seg->seq+len-1))){ /* Straddles */
  842.                 accept++;
  843.             }
  844.         }
  845.     }
  846.     if(!accept){
  847.         tcb->rerecv += len;    /* Assume all of it was a duplicate */
  848.         free_p(*bpp);
  849.         return -1;
  850.     }
  851.     if((dupcnt = tcb->rcv.nxt - seg->seq) > 0){
  852.         tcb->rerecv += dupcnt;
  853.         /* Trim off SYN if present */
  854.         if(seg->flags.syn){
  855.             /* SYN is before first data byte */
  856.             seg->flags.syn = 0;
  857.             seg->seq++;
  858.             dupcnt--;
  859.         }
  860.         if(dupcnt > 0){
  861.             pullup(bpp,NULLCHAR,(int16)dupcnt);
  862.             seg->seq += dupcnt;
  863.             *length -= dupcnt;
  864.         }
  865.     }
  866.     if((excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd)) > 0){
  867.         tcb->rerecv += excess;
  868.         /* Trim right edge */
  869.         *length -= excess;
  870.         trim_mbuf(bpp,*length);
  871.         seg->flags.fin = 0;    /* FIN follows last data byte */
  872.     }
  873.     return 0;
  874. }
  875.